In [1]:
    
%matplotlib inline
    
Adapted from: http://mpld3.github.io/examples/custom_plugin.html
In [2]:
    
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import mpld3
from mpld3 import plugins, utils
import math
    
In [3]:
    
class LinkedView(plugins.PluginBase):
    """A simple plugin showing how multiple axes can be linked"""
    JAVASCRIPT = """
    mpld3.register_plugin("linkedview", LinkedViewPlugin);
    LinkedViewPlugin.prototype = Object.create(mpld3.Plugin.prototype);
    LinkedViewPlugin.prototype.constructor = LinkedViewPlugin;
    LinkedViewPlugin.prototype.requiredProps = ["idpts", "idline", "data"];
    LinkedViewPlugin.prototype.defaultProps = {}
    function LinkedViewPlugin(fig, props){
        mpld3.Plugin.call(this, fig, props);
    };
    LinkedViewPlugin.prototype.draw = function(){
      var pts = mpld3.get_element(this.props.idpts);
      var line = mpld3.get_element(this.props.idline);
      var data = this.props.data;
      function mouseover(d, i){
        line.data = data[i];
        line.elements().transition()
            .attr("d", line.datafunc(line.data))
            .style("stroke", this.style.fill);
      }
      pts.elements().on("mouseover", mouseover);
    };
    """
    def __init__(self, points, line, linedata):
        if isinstance(points, matplotlib.lines.Line2D):
            suffix = "pts"
        else:
            suffix = None
        self.dict_ = {"type": "linkedview",
                      "idpts": utils.get_id(points, suffix),
                      "idline": utils.get_id(line),
                      "data": linedata}
    
In [4]:
    
nmax=1e6
    
In [126]:
    
# scatter periods and amplitudes
np.random.seed(0)
P = np.linspace(-math.log10(nmax), 0, num=20)
#P = 0.2 + np.random.random(size=20)
#M = nmax*np.random.random(size=20)
M = np.ceil(np.linspace(1,nmax,num=20))
x = np.ceil(np.linspace(1,nmax,num=100))
data = np.array([[x, ((x<Mi)*(x-Mi) + Mi )*x ]
                 for (Mi, Pi) in zip(M, P)])
    
In [127]:
    
Mi=1e5
((x<Mi)*x + (x>Mi)*([Mi]*len(x)) )
((x<Mi)*(x-Mi) + Mi )
    
    Out[127]:
In [128]:
    
cdict = {'red':   [(0.0,  0.0, 0.0),
                   (1.0,  1.0, 1.0)],
         'green': [(0.0,  0.0, 0.0),
                   (1.0,  0.0, 0.0)],
         'blue':  [(0.0,  0.0, 0.0),
                   (1.0,  0.0, 0.0)]}
cmap = matplotlib.colors.LinearSegmentedColormap('Red', cdict)
    
In [129]:
    
x
    
    Out[129]:
In [141]:
    
fig, ax = plt.subplots(2)
points = ax[1].scatter(M, P, c=-(P+min(P))/min(P), cmap=cmap, 
                       s=400*(M/nmax), alpha=0.5)
ax[1].set_xlabel('# machines')
ax[1].set_xlim(1,nmax)
ax[1].set_ylabel('log(Fraction of reds)')
ax[1].set_ylim(-math.log10(nmax), 0)
# create the line object
lines = ax[0].plot(x, 0 * x, '-w', lw=3, alpha=0.5)
ax[0].set_xlabel('# nodes')
ax[0].set_xlim(0, nmax)
ax[0].set_ylabel('# messages')
ax[0].set_ylim(1, max(max(linedata))[1])
ax[0].set_title("Hover over points to see lines")
# transpose line data and add plugin
linedata = data.transpose(0, 2, 1).tolist()
plugins.connect(fig, LinkedView(points, lines[0], linedata))
fig.tight_layout()
mpld3.display()
    
    Out[141]:
In [136]:
    
max(max(linedata))[1]
    
    Out[136]:
In [137]:
    
fig2, ax2 = plt.subplots(1)
    
    
In [109]:
    
ax2.plot(x,linedata)
    
    
In [121]:
    
linedata[0]
    
    Out[121]:
In [ ]: